package com.wing.user.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.cvm.v20170312.CvmClient;
import com.tencentcloudapi.cvm.v20170312.models.*;
import com.wing.user.dao.CloudServerDao;
import com.wing.user.dao.FaceRecognitionDao;
import com.wing.user.model.entity.CloudServer;
import com.wing.user.model.response.EnterpriseInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * 云服务器-ServiceImpl
 *
 * @author
 */

@Service
@Slf4j
public class CloudServerServiceImpl extends ServiceImpl<CloudServerDao, CloudServer> implements CloudServerService {

    @Value("${tencent.face.id}")
    private String secretId;
    @Value("${tencent.face.key}")
    private String secretKey;
    @Value("${domain.name}")
    private String domainName;
    @Autowired
    private FaceRecognitionDao faceRecognitionDao;

    @Override
    public JSONObject runInstances() {
        JSONObject json = new JSONObject();
        try{
            // 实例化一个认证对象，入参需要传入腾讯云账户secretId，secretKey,此处还需注意密钥对的保密
            // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
            Credential cred = new Credential("SecretId", "SecretKey");
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("cvm.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            CvmClient client = new CvmClient(cred, "ap-guangzhou", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            // 文档网址：https://cloud.tencent.com/document/product/213/15730
            RunInstancesRequest req = new RunInstancesRequest();
            /**
             * 实例计费类型。
             * PREPAID：预付费，即包年包月
             * POSTPAID_BY_HOUR：按小时后付费
             * CDHPAID：独享子机（基于专用宿主机创建，宿主机部分的资源不收费）
             * SPOTPAID：竞价付费
             * CDCPAID：专用集群付费
             * 默认值：POSTPAID_BY_HOUR。
             */
            req.setInstanceChargeType("POSTPAID_BY_HOUR");
            /**
             * 实例所在的位置。通过该参数可以指定实例所属可用区，所属项目，所属宿主机（在专用宿主机上创建子机时指定）等属性。
             * 注：如果您不指定LaunchTemplate参数，则Placement为必选参数。若同时传递Placement和LaunchTemplate，则默认覆盖LaunchTemplate中对应的Placement的值。
             */
            Placement placement1 = new Placement();
            /**
             * 实例所属的可用区ID。该参数可以通过调用 DescribeZones 的返回值中的Zone字段来获取。
             */
            placement1.setZone("ap-nanjing-1");
            req.setPlacement(placement1);
            /**
             * 实例机型。不同实例机型指定了不同的资源规格。
             *
             * 对于付费模式为PREPAID或POSTPAID_BY_HOUR的实例创建，具体取值可通过调用接口DescribeInstanceTypeConfigs来获得最新的规格表或参见实例规格描述。若不指定该参数，则系统将根据当前地域的资源售卖情况动态指定默认机型。
             * 对于付费模式为CDHPAID的实例创建，该参数以"CDH_"为前缀，根据CPU和内存配置生成，具体形式为：CDH_XCXG，例如对于创建CPU为1核，内存为1G大小的专用宿主机的实例，该参数应该为CDH_1C1G。
             */
            req.setInstanceType("S5.2XLARGE32"); // 标准型S5 - 8核 32G
            /**
             * 指定有效的镜像ID，格式形如img-xxx。镜像类型分为四种：
             * 公共镜像
             * 自定义镜像
             * 共享镜像
             * 服务市场镜像
             *
             * 可通过以下方式获取可用的镜像ID：
             * 公共镜像、自定义镜像、共享镜像的镜像ID可通过登录控制台查询；服务镜像市场的镜像ID可通过云市场查询。
             * 通过调用接口 DescribeImages ，传入InstanceType获取当前机型支持的镜像列表，取返回信息中的ImageId字段。
             *
             * 注：如果您不指定LaunchTemplate参数，则ImageId为必选参数。若同时传递ImageId和LaunchTemplate，则默认覆盖LaunchTemplate中对应的ImageId的值。
             */
//            req.setImageId("img-9xqekomx"); // 公共镜像 CentOS Stream 9 64位
            req.setImageId("img-oxu57ops"); // 自定义镜像：企业端镜像 CentOS Stream 9 64位
            /**
             * 实例系统盘配置信息。若不指定该参数，则按照系统默认值进行分配。
             */
            SystemDisk systemDisk1 = new SystemDisk();
            /**
             * 系统盘类型。系统盘类型限制详见存储概述。取值范围：
             * LOCAL_BASIC：本地硬盘
             * LOCAL_SSD：本地SSD硬盘
             * CLOUD_BASIC：普通云硬盘
             * CLOUD_SSD：SSD云硬盘
             * CLOUD_PREMIUM：高性能云硬盘
             *
             * 默认取值：当前有库存的硬盘类型。
             */
            systemDisk1.setDiskType("CLOUD_PREMIUM");
            /**
             * 系统盘大小，单位：GB。默认值为 50
             */
            systemDisk1.setDiskSize(50L);
            req.setSystemDisk(systemDisk1);
            /**
             * 实例数据盘配置信息。若不指定该参数，则默认不购买数据盘。支持购买的时候指定21块数据盘，其中最多包含1块LOCAL_BASIC数据盘或者LOCAL_SSD数据盘，最多包含20块CLOUD_BASIC数据盘、CLOUD_PREMIUM数据盘或者CLOUD_SSD数据盘。
             */
            DataDisk[] dataDisks1 = new DataDisk[1];
            DataDisk dataDisk1 = new DataDisk();
            /**
             * 数据盘类型。数据盘类型限制详见存储概述。取值范围：
             * LOCAL_BASIC：本地硬盘
             * LOCAL_SSD：本地SSD硬盘
             * LOCAL_NVME：本地NVME硬盘，与InstanceType强相关，不支持指定
             * LOCAL_PRO：本地HDD硬盘，与InstanceType强相关，不支持指定
             * CLOUD_BASIC：普通云硬盘
             * CLOUD_PREMIUM：高性能云硬盘
             * CLOUD_SSD：SSD云硬盘
             * CLOUD_HSSD：增强型SSD云硬盘
             * CLOUD_TSSD：极速型SSD云硬盘
             *
             * 默认取值：LOCAL_BASIC。
             *
             * 该参数对ResizeInstanceDisk接口无效。
             */
            dataDisk1.setDiskType("CLOUD_PREMIUM");
            /**
             * 数据盘大小，单位：GB。最小调整步长为10G，不同数据盘类型取值范围不同，具体限制详见：存储概述。默认值为0，表示不购买数据盘。更多限制详见产品文档。
             */
            dataDisk1.setDiskSize(40L);
            dataDisks1[0] = dataDisk1;
            req.setDataDisks(dataDisks1);
            /**
             * 公网带宽相关信息设置。若不指定该参数，则默认公网带宽为0Mbps。
             */
            InternetAccessible internetAccessible1 = new InternetAccessible();
            /**
             * 网络计费类型。取值范围：
             * BANDWIDTH_PREPAID：预付费按带宽结算
             * TRAFFIC_POSTPAID_BY_HOUR：流量按小时后付费
             * BANDWIDTH_POSTPAID_BY_HOUR：带宽按小时后付费
             * BANDWIDTH_PACKAGE：带宽包用户
             * 默认取值：非带宽包用户默认与子机付费类型保持一致。
             */
            internetAccessible1.setInternetChargeType("TRAFFIC_POSTPAID_BY_HOUR");
            /**
             * 公网出带宽上限，单位：Mbps。默认值：0Mbps。不同机型带宽上限范围不一致，具体限制详见购买网络带宽。
             */
            internetAccessible1.setInternetMaxBandwidthOut(10L);
            /**
             * 是否分配公网IP。取值范围：
             * TRUE：表示分配公网IP
             * FALSE：表示不分配公网IP
             *
             * 当公网带宽大于0Mbps时，可自由选择开通与否，默认开通公网IP；当公网带宽为0，则不允许分配公网IP。该参数仅在RunInstances接口中作为入参使用。
             */
            internetAccessible1.setPublicIpAssigned(true);
            req.setInternetAccessible(internetAccessible1);
            /**
             * 购买实例数量。包年包月实例取值范围：[1，300]，按量计费实例取值范围：[1，100]。默认取值：1。指定购买实例的数量不能超过用户所能购买的剩余配额数量，具体配额相关限制详见CVM实例购买限制。
             */
            req.setInstanceCount(1L);
            /**
             * 实例显示名称。
             * 不指定实例显示名称则默认显示‘未命名’。
             * 购买多台实例，如果指定模式串{R:x}，表示生成数字[x, x+n-1]，其中n表示购买实例的数量，例如server_{R:3}，购买1台时，实例显示名称为server_3；购买2台时，实例显示名称分别为server_3，server_4。支持指定多个模式串{R:x}。
             * 购买多台实例，如果不指定模式串，则在实例显示名称添加后缀1、2...n，其中n表示购买实例的数量，例如server_，购买2台时，实例显示名称分别为server_1，server_2。
             * 最多支持60个字符（包含模式串）。
             */
            EnterpriseInfoVO enterpriseInfoVO = faceRecognitionDao.getEnterpriseInfo();
            req.setInstanceName(enterpriseInfoVO.getEnterpriseName()+"-企业端");
            /**
             * 增强服务。通过该参数可以指定是否开启云安全、云监控等服务。若不指定该参数，则默认公共镜像开启云监控、云安全服务；自定义镜像与镜像市场镜像默认不开启云监控，云安全服务，而使用镜像里保留的服务。
             */
            EnhancedService enhancedService1 = new EnhancedService();
            RunSecurityServiceEnabled runSecurityServiceEnabled1 = new RunSecurityServiceEnabled();
            /**
             * 开启云安全服务。若不指定该参数，则默认开启云安全服务。
             */
            runSecurityServiceEnabled1.setEnabled(true);
            enhancedService1.setSecurityService(runSecurityServiceEnabled1);

            RunMonitorServiceEnabled runMonitorServiceEnabled1 = new RunMonitorServiceEnabled();
            /**
             * 开启云监控服务。若不指定该参数，则默认开启云监控服务。
             */
            runMonitorServiceEnabled1.setEnabled(true);
            enhancedService1.setMonitorService(runMonitorServiceEnabled1);

            req.setEnhancedService(enhancedService1);

            // 返回的resp是一个RunInstancesResponse的实例，与请求对象对应
            RunInstancesResponse resp = client.RunInstances(req);
            // 输出json格式的字符串回包
            System.out.println(RunInstancesResponse.toJsonString(resp));
            json = JSON.parseObject(RunInstancesResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
        return json;
    }

    public static void main(String[] args){
        try{
            String secretId = "AKIDXtzoMefPs51g4pJWS7VcRzGGzRbU7TYN";
            String secretKey = "Zrsb3E8k59wReaGelbASTCepiKehTxA6";
            // 实例化一个认证对象，入参需要传入腾讯云账户secretId，secretKey,此处还需注意密钥对的保密
            // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
            Credential cred = new Credential(secretId, secretKey);
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("cvm.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            CvmClient client = new CvmClient(cred, "ap-nanjing", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            // 文档网址：https://cloud.tencent.com/document/product/213/15730
            RunInstancesRequest req = new RunInstancesRequest();
            /**
             * 实例计费类型。
             * PREPAID：预付费，即包年包月
             * POSTPAID_BY_HOUR：按小时后付费
             * CDHPAID：独享子机（基于专用宿主机创建，宿主机部分的资源不收费）
             * SPOTPAID：竞价付费
             * CDCPAID：专用集群付费
             * 默认值：POSTPAID_BY_HOUR。
             */
//            req.setInstanceChargeType("POSTPAID_BY_HOUR");
            req.setInstanceChargeType("PREPAID");

            /**
             * 预付费模式，即包年包月相关参数设置。通过该参数可以指定包年包月实例的购买时长、是否设置自动续费等属性。若指定实例的付费模式为预付费则该参数必传。
             */
            InstanceChargePrepaid instanceChargePrepaid1 = new InstanceChargePrepaid();
            instanceChargePrepaid1.setPeriod(1L); // 购买实例的时长，单位：月。取值范围：1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 24, 36, 48, 60。
            req.setInstanceChargePrepaid(instanceChargePrepaid1);

            /**
             * 实例所在的位置。通过该参数可以指定实例所属可用区，所属项目，所属宿主机（在专用宿主机上创建子机时指定）等属性。
             * 注：如果您不指定LaunchTemplate参数，则Placement为必选参数。若同时传递Placement和LaunchTemplate，则默认覆盖LaunchTemplate中对应的Placement的值。
             */
            Placement placement1 = new Placement();
            /**
             * 实例所属的可用区ID。该参数可以通过调用 DescribeZones 的返回值中的Zone字段来获取。
             */
            placement1.setZone("ap-nanjing-1");
            req.setPlacement(placement1);
            /**
             * 实例机型。不同实例机型指定了不同的资源规格。
             *
             * 对于付费模式为PREPAID或POSTPAID_BY_HOUR的实例创建，具体取值可通过调用接口DescribeInstanceTypeConfigs来获得最新的规格表或参见实例规格描述。若不指定该参数，则系统将根据当前地域的资源售卖情况动态指定默认机型。
             * 对于付费模式为CDHPAID的实例创建，该参数以"CDH_"为前缀，根据CPU和内存配置生成，具体形式为：CDH_XCXG，例如对于创建CPU为1核，内存为1G大小的专用宿主机的实例，该参数应该为CDH_1C1G。
             */
            req.setInstanceType("S5.2XLARGE32"); // 标准型S5 - 8核 32G
            /**
             * 指定有效的镜像ID，格式形如img-xxx。镜像类型分为四种：
             * 公共镜像
             * 自定义镜像
             * 共享镜像
             * 服务市场镜像
             *
             * 可通过以下方式获取可用的镜像ID：
             * 公共镜像、自定义镜像、共享镜像的镜像ID可通过登录控制台查询；服务镜像市场的镜像ID可通过云市场查询。
             * 通过调用接口 DescribeImages ，传入InstanceType获取当前机型支持的镜像列表，取返回信息中的ImageId字段。
             *
             * 注：如果您不指定LaunchTemplate参数，则ImageId为必选参数。若同时传递ImageId和LaunchTemplate，则默认覆盖LaunchTemplate中对应的ImageId的值。
             */
//            req.setImageId("img-9xqekomx"); // 公共镜像 CentOS Stream 9 64位
            req.setImageId("img-oxu57ops"); // 自定义镜像：企业端镜像 CentOS Stream 9 64位
            /**
             * 实例系统盘配置信息。若不指定该参数，则按照系统默认值进行分配。
             */
            SystemDisk systemDisk1 = new SystemDisk();
            /**
             * 系统盘类型。系统盘类型限制详见存储概述。取值范围：
             * LOCAL_BASIC：本地硬盘
             * LOCAL_SSD：本地SSD硬盘
             * CLOUD_BASIC：普通云硬盘
             * CLOUD_SSD：SSD云硬盘
             * CLOUD_PREMIUM：高性能云硬盘
             *
             * 默认取值：当前有库存的硬盘类型。
             */
            systemDisk1.setDiskType("CLOUD_PREMIUM");
            /**
             * 系统盘大小，单位：GB。默认值为 50
             */
            systemDisk1.setDiskSize(50L);
            req.setSystemDisk(systemDisk1);
            /**
             * 实例数据盘配置信息。若不指定该参数，则默认不购买数据盘。支持购买的时候指定21块数据盘，其中最多包含1块LOCAL_BASIC数据盘或者LOCAL_SSD数据盘，最多包含20块CLOUD_BASIC数据盘、CLOUD_PREMIUM数据盘或者CLOUD_SSD数据盘。
             */
            DataDisk[] dataDisks1 = new DataDisk[1];
            DataDisk dataDisk1 = new DataDisk();
            /**
             * 数据盘类型。数据盘类型限制详见存储概述。取值范围：
             * LOCAL_BASIC：本地硬盘
             * LOCAL_SSD：本地SSD硬盘
             * LOCAL_NVME：本地NVME硬盘，与InstanceType强相关，不支持指定
             * LOCAL_PRO：本地HDD硬盘，与InstanceType强相关，不支持指定
             * CLOUD_BASIC：普通云硬盘
             * CLOUD_PREMIUM：高性能云硬盘
             * CLOUD_SSD：SSD云硬盘
             * CLOUD_HSSD：增强型SSD云硬盘
             * CLOUD_TSSD：极速型SSD云硬盘
             *
             * 默认取值：LOCAL_BASIC。
             *
             * 该参数对ResizeInstanceDisk接口无效。
             */
            dataDisk1.setDiskType("CLOUD_PREMIUM");
            /**
             * 数据盘大小，单位：GB。最小调整步长为10G，不同数据盘类型取值范围不同，具体限制详见：存储概述。默认值为0，表示不购买数据盘。更多限制详见产品文档。
             */
            dataDisk1.setDiskSize(40L);
            dataDisks1[0] = dataDisk1;
            req.setDataDisks(dataDisks1);
            /**
             * 公网带宽相关信息设置。若不指定该参数，则默认公网带宽为0Mbps。
             */
            InternetAccessible internetAccessible1 = new InternetAccessible();
            /**
             * 网络计费类型。取值范围：
             * BANDWIDTH_PREPAID：预付费按带宽结算
             * TRAFFIC_POSTPAID_BY_HOUR：流量按小时后付费
             * BANDWIDTH_POSTPAID_BY_HOUR：带宽按小时后付费
             * BANDWIDTH_PACKAGE：带宽包用户
             * 默认取值：非带宽包用户默认与子机付费类型保持一致。
             */
            internetAccessible1.setInternetChargeType("TRAFFIC_POSTPAID_BY_HOUR");
            /**
             * 公网出带宽上限，单位：Mbps。默认值：0Mbps。不同机型带宽上限范围不一致，具体限制详见购买网络带宽。
             */
            internetAccessible1.setInternetMaxBandwidthOut(10L);
            /**
             * 是否分配公网IP。取值范围：
             * TRUE：表示分配公网IP
             * FALSE：表示不分配公网IP
             *
             * 当公网带宽大于0Mbps时，可自由选择开通与否，默认开通公网IP；当公网带宽为0，则不允许分配公网IP。该参数仅在RunInstances接口中作为入参使用。
             */
            internetAccessible1.setPublicIpAssigned(true);
            req.setInternetAccessible(internetAccessible1);
            /**
             * 购买实例数量。包年包月实例取值范围：[1，300]，按量计费实例取值范围：[1，100]。默认取值：1。指定购买实例的数量不能超过用户所能购买的剩余配额数量，具体配额相关限制详见CVM实例购买限制。
             */
            req.setInstanceCount(1L);
            /**
             * 实例显示名称。
             * 不指定实例显示名称则默认显示‘未命名’。
             * 购买多台实例，如果指定模式串{R:x}，表示生成数字[x, x+n-1]，其中n表示购买实例的数量，例如server_{R:3}，购买1台时，实例显示名称为server_3；购买2台时，实例显示名称分别为server_3，server_4。支持指定多个模式串{R:x}。
             * 购买多台实例，如果不指定模式串，则在实例显示名称添加后缀1、2...n，其中n表示购买实例的数量，例如server_，购买2台时，实例显示名称分别为server_1，server_2。
             * 最多支持60个字符（包含模式串）。
             */
            req.setInstanceName("测试服务器");
            /**
             * 增强服务。通过该参数可以指定是否开启云安全、云监控等服务。若不指定该参数，则默认公共镜像开启云监控、云安全服务；自定义镜像与镜像市场镜像默认不开启云监控，云安全服务，而使用镜像里保留的服务。
             */
            EnhancedService enhancedService1 = new EnhancedService();
            RunSecurityServiceEnabled runSecurityServiceEnabled1 = new RunSecurityServiceEnabled();
            /**
             * 开启云安全服务。若不指定该参数，则默认开启云安全服务。
             */
            runSecurityServiceEnabled1.setEnabled(true);
            enhancedService1.setSecurityService(runSecurityServiceEnabled1);

            RunMonitorServiceEnabled runMonitorServiceEnabled1 = new RunMonitorServiceEnabled();
            /**
             * 开启云监控服务。若不指定该参数，则默认开启云监控服务。
             */
            runMonitorServiceEnabled1.setEnabled(true);
            enhancedService1.setMonitorService(runMonitorServiceEnabled1);

            req.setEnhancedService(enhancedService1);

            // 返回的resp是一个RunInstancesResponse的实例，与请求对象对应
            RunInstancesResponse resp = client.RunInstances(req);
            // 输出json格式的字符串回包
            System.out.println(RunInstancesResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
    }

}
